package es

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/xiao_hange/go-admin-pkg/pkg/logger"
	"github.com/olivere/elastic/v7"
)

var (
	IndexAlreadyExists = errors.New("索引已存在")
	CreationFailed     = errors.New("索引创建失败")
)

type Service struct {
	client *elastic.Client
	l      logger.AppLogger
}

func NewService(c *elastic.Client, l logger.AppLogger) *Service {
	return &Service{
		client: c,
		l:      l,
	}
}

func (s *Service) CreateIndex(ctx context.Context, index string, mapping string) (bool, error) {

	exists, err := s.client.IndexExists(index).Do(ctx)

	if err != nil {
		s.l.Error("查询搜索是否存在失败", logger.Error(err))
		return false, err
	}

	if !exists {
		_, err = s.client.CreateIndex(index).BodyString(mapping).Do(ctx)
		if err != nil {
			s.l.Error("索引创建失败", logger.Error(err))
			return false, err
		}
	} else {
		return false, IndexAlreadyExists
	}
	return true, nil
}

func (s *Service) InsertDocument(ctx context.Context, index string, documentID string, document any) (bool, error) {
	exists, err := s.client.IndexExists(index).Do(ctx)

	if err != nil {
		s.l.Error("查询索引是否存在失败", logger.Error(err))
		return false, err
	}

	if exists {
		// 如果索引存在，则插入文档
		_, err = s.client.Index().Index(index).Id(documentID).BodyJson(document).Do(ctx)

		if err != nil {
			s.l.Error("插入文档失败", logger.Error(err))
			return false, err
		}

		return true, nil
	}

	return false, fmt.Errorf("索引不存在: %s", index)
}

func (s *Service) SearchDocuments(ctx context.Context, index string, query elastic.Query, highlight *elastic.Highlight) ([]map[string]any, error) {
	if query == nil {
		query = elastic.NewBoolQuery()
	}
	search := s.client.Search(index).Query(query).From(1).Size(10)

	if highlight != nil {
		search.Highlight(highlight)
	}
	searchResult, err := search.Do(ctx)
	if err != nil {
		return nil, err
	}

	if err != nil {
		s.l.Error("搜索文档失败", logger.Error(err))
		return nil, err
	}

	var results []map[string]any

	for _, hit := range searchResult.Hits.Hits {
		var result map[string]any
		if err := json.Unmarshal(hit.Source, &result); err != nil {
			s.l.Error("解析搜索结果失败", logger.Error(err))
			return nil, err
		}
		results = append(results, result)
		fmt.Println(result)
	}

	return results, nil
}
